home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / PASCAL / 0187.ZIP / LANDER.PAS < prev    next >
Pascal/Delphi Source File  |  1985-01-20  |  9KB  |  409 lines

  1. program lander;
  2.  
  3. const
  4.    instrfile      = 'LANDINST.DAT';
  5.    maxrand        = 32767;
  6.    timeinc        = 0.1;
  7.    slightly       = 0.1;
  8.    moderately     = 0.2;
  9.    very           = 0.3;
  10.    impossible     = 0.5;
  11.    certainty      = 1.0;
  12.    minmeteors     = 2.0;
  13.    maxmeteors     = 7.0;
  14.    eachmisschance = 0.8;
  15.    minavoid       = 10;
  16.    landingheight  = 0.1;
  17.    crashlandspeed = 6.0;
  18.  
  19. type
  20.    answers = set of 'A'..'Z';
  21.    str80 = string[80];
  22.  
  23. var
  24.    speed, height, gravity : real;
  25.    maxlandingspeed        : real;
  26.    chance, misschance     : real;
  27.    burn, fuel             : integer;
  28.    nummeteors             : integer;
  29.    inp                    : string[10];
  30.    ranout                 : boolean;
  31.  
  32. (*
  33.  * returns a random real number between lowlimit and highlimit
  34.  *)
  35.  
  36. function rand(lowlimit, highlimit : real) : real;
  37.  
  38. begin
  39.    rand := lowlimit + (highlimit - lowlimit + 1) * random;
  40. end;
  41.  
  42. (*
  43.  * returns true if a random number, weighted by the difficulty level, is
  44.  * less than the argument
  45.  *)
  46.  
  47. function unlucky(percentchance : real) : boolean;
  48.  
  49. begin
  50.    unlucky := rand(0.0, 1.0 - chance) <= percentchance;
  51. end;
  52.  
  53. (*
  54.  * converts a numerical ascii character to its corresponding integral value
  55.  *)
  56.  
  57. function asciitoint(digit : char) : integer;
  58.  
  59. begin
  60.    asciitoint := ord(digit) - ord('0');
  61. end;
  62.  
  63. (*
  64.  * returns true if the argument is a numerical digit
  65.  *)
  66.  
  67. function isdigit(ch : char) : boolean;
  68.  
  69. begin
  70.    isdigit := (ch >= '0') and (ch <= '9');
  71. end;
  72.  
  73. (*
  74.  * convert determines the numerical value of the digits ina string. it returns
  75.  * the integer and updates the string to now contain whatever was after the
  76.  * end of the number. if the string is blank, the value is zero; if a number
  77.  * is not found it returns -1.
  78.  *)
  79.  
  80. function convert(numstring : str80) : integer;
  81.  
  82. var
  83.    intvalue       : integer;
  84.    position       : integer;
  85.    digitsfound    : integer;
  86.    endofnumber    : boolean;
  87.    notinteresting : boolean;
  88.  
  89. begin
  90.    intvalue := 0;
  91.    digitsfound := 0;
  92.    position := 1;
  93.    endofnumber := false;
  94.    notinteresting := true;
  95.    if length(numstring) > 0 then
  96.       begin
  97.       while (position < length(numstring)) and notinteresting do
  98.          if numstring[position] = ' ' then
  99.             position := position + 1
  100.          else
  101.             notinteresting := false;
  102.       while (position <= length(numstring)) and (not endofnumber) do
  103.          if isdigit(numstring[position]) then
  104.             begin
  105.             intvalue := intvalue * 10 + asciitoint(numstring[position]);
  106.             position := position + 1;
  107.             digitsfound := digitsfound + 1;
  108.             end
  109.          else
  110.             endofnumber := true;
  111.       if digitsfound = 0 then
  112.          intvalue := -1;
  113.       end;
  114.    convert := intvalue;
  115. end;
  116.  
  117. (*
  118.  * asks a question with a single character answer. if the response is in the
  119.  * set 'answers', the letter is returned. otherwise the string ifbad is
  120.  * printed and the question is asked again.
  121.  *)
  122.  
  123. function ask(question, ifbad : str80; responses : answers) : char;
  124.  
  125. var
  126.    bad : boolean;
  127.    ch  : char;
  128.  
  129. begin
  130.    bad := true;
  131.    repeat
  132.       write(question);
  133.       readln(ch);
  134.       writeln;
  135.       if ch in responses then
  136.          bad := false
  137.       else
  138.          writeln(ifbad);
  139.    until not bad;
  140.    ask := ch;
  141. end;
  142.  
  143. (*
  144.  * prints out the instructions from a file instrfile
  145.  *)
  146.  
  147. procedure instructions;
  148.  
  149. var
  150.    instruct : text;
  151.    ch       : char;
  152.    str      : string[80];
  153.  
  154. begin
  155.    assign(instruct,instrfile);
  156.    reset(instruct);
  157.    while not eof(instruct) do
  158.       begin
  159.       readln(instruct,str);
  160.       writeln(str);
  161.       end;
  162. end;
  163.  
  164. procedure startup;
  165.  
  166. begin
  167.    if ask('Do you want instructions? ','Please answer Y or N',['Y','N']) = 'Y' then
  168.       instructions;
  169.    randomize;
  170. end;
  171.  
  172. (*
  173.  * ask the player for the difficulty level of the next landing
  174.  *)
  175.  
  176. procedure getdifficulty;
  177.  
  178. var
  179.    level : char;
  180.  
  181. begin
  182.    level := ask('Level of difficulty? ','B:Beginner, E:Expert, N:Navigator, A:Astronaut',
  183.                  ['B','E','N','A']);
  184.    case level of
  185.       'B' : chance := slightly;
  186.       'E' : chance := moderately;
  187.       'N' : chance := very;
  188.       'A' : chance := impossible;
  189.    end;
  190. end;
  191.  
  192. (*
  193.  * variables that must be re-set each time a new landing is attempted
  194.  *)
  195.  
  196. procedure startgame;
  197.  
  198. begin
  199.    getdifficulty;
  200.    gravity := rand(9.0 + chance, 11.0 + chance);
  201.    height  := rand(1.0 + chance, 2.0 + chance) * 100.0;
  202.    speed   := rand(0.0, 100.0 * chance) + 30.0;
  203.    fuel    := round(50.0 * rand(3.0 - chance, 4.0 - chance));
  204.    maxlandingspeed := crashlandspeed - 10.0 * chance;
  205.    misschance := certainty;
  206.    ranout := false;
  207. end;
  208.  
  209. (*
  210.  * tell player his height, speed and direction
  211.  *)
  212.  
  213. procedure writestatus;
  214.  
  215. begin
  216.    writeln;
  217.    write('You are ');
  218.    if speed > 0.0 then
  219.       write('falling')
  220.    else
  221.       write('rising');
  222.    writeln(' from a height of ',height:1:1);
  223.    writeln('meters at ',abs(speed):1:1,' m/s.');
  224.    if not ranout then
  225.       writeln('There are ',fuel:1,' liters of fuel left.');
  226.    ranout := fuel = 0;
  227. end;
  228.  
  229. (*
  230.  * determines if there are any meteors, and if so, how many
  231.  *)
  232.  
  233. procedure lookformeteors;
  234.  
  235. var
  236.    eachrock : integer;
  237.  
  238. begin
  239.    misschance := certainty;
  240.    if unlucky(0.1) then
  241.       begin
  242.       nummeteors := round(rand(minmeteors,maxmeteors + 10.0 * chance));
  243.       for eachrock := 1 to nummeteors do
  244.          misschance := misschance * eachmisschance;
  245.       writeln('We are on a collision course with ',nummeteors:1);
  246.       write('meteors.');
  247.       if ranout then
  248.          writeln
  249.       else
  250.          begin
  251.          writeln('If we do not use more than ',minavoid:1,'liters of fuel in the');
  252.          writeln('next second, there is a ',round(100.0*(1.0-misschance)),
  253.                  ' % probability that we will be');
  254.          writeln('hit. If more is used it will be only 10 %.');
  255.          end;
  256.    end;
  257. end;
  258.  
  259. (*
  260.  * asks the player for the amount of fuel to use in the next time period.
  261.  *)
  262.  
  263. procedure getburn;
  264.  
  265. const
  266.    fuelprompt = 'Units of fuel : ';
  267.  
  268. begin
  269.    repeat
  270.       write(fuelprompt);
  271.       readln(inp);
  272.       burn := convert(inp);
  273.       if burn > fuel then
  274.          writeln('There isn''t that much fuel left.')
  275.       else if burn < 0 then
  276.          writeln('I don''t think that''s possible.');
  277.    until (burn <= fuel) and (burn >= 0);
  278. end;
  279.  
  280. (*
  281.  * figure out the craft's new speed according to the laws of physics
  282.  *)
  283.  
  284. procedure updatestatus;
  285.  
  286. var
  287.    deltat : integer;
  288.  
  289. begin
  290.    fuel := fuel - burn;
  291.    deltat := 0;
  292.    repeat
  293.       deltat := deltat + 1;
  294.       height := height - speed * timeinc - (gravity - burn) * 0.5 * sqr(timeinc);
  295.       speed := speed + (gravity - burn) * timeinc;
  296.    until (deltat = trunc(1 / timeinc)) or (height <= landingheight);
  297. end;
  298.  
  299. (*
  300.  * all the procedures that make a turn
  301.  *)
  302.  
  303. procedure doaturn;
  304.  
  305. begin
  306.    writestatus;
  307.    lookformeteors;
  308.    if fuel > 0 then
  309.       getburn
  310.    else
  311.       burn := 0;
  312.    updatestatus;
  313. end;
  314.  
  315. (*
  316.  * the course has changed: meteors have a lower chance of hitting
  317.  *)
  318.  
  319. function coursechanged : boolean;
  320.  
  321. begin
  322.    if unlucky(0.1) then
  323.       begin
  324.       writeln('Despite the precautionary measures taken, the ship was destroyed.');
  325.       coursechanged := true;
  326.       end
  327.    else
  328.       begin
  329.       writeln('Your prudent actions saved the ship from the menacing meteors!');
  330.       coursechanged := false;
  331.       end
  332. end;
  333.  
  334. function coursesame: boolean;
  335.  
  336. begin
  337.    if not unlucky(1.0 - misschance) then
  338.       begin
  339.       writeln('Your piloting skills have steered you through the center of the swarm!');
  340.       coursesame := false;
  341.       end
  342.    else if ranout then
  343.       begin
  344.       writeln('What a pity .. your craft was demolished by meteors before it could');
  345.       writeln('be vaporized on contact with the surface.');
  346.       coursesame := true;
  347.       end
  348.    else
  349.       begin
  350.       writeln('Your pointless gambling has destroyed the ship, you foolish plebe!');
  351.       coursesame := true;
  352.       end;
  353. end;
  354.  
  355. (*
  356.  * figures if any meteors (if there were any) managed to hit the ship.
  357.  * different messages are printed depending on the thrust of the last turn.
  358.  *)
  359.  
  360.  
  361. function anyhit : boolean;
  362.  
  363. begin
  364.    if (misschance = certainty) or (height <= landingheight) then
  365.       anyhit := false
  366.    else if burn > minavoid then
  367.       anyhit := coursechanged
  368.    else
  369.       anyhit := coursesame;
  370. end;
  371.  
  372. (*
  373.  * returns true if the ship has come close enough to the ground that we can
  374.  * say it has landed. could crash or touch down safely.
  375.  *)
  376.  
  377. function landed : boolean;
  378.  
  379. begin
  380.    if height < landingheight then
  381.       begin
  382.       speed := abs(speed);
  383.       if speed < maxlandingspeed then
  384.          write('We have landed safely')
  385.       else
  386.          write('We have crashed');
  387.       writeln(' at a speed of ',speed:1:1,' meters/second.');
  388.       landed := true;
  389.       end
  390.    else
  391.       landed := false;
  392. end;
  393.  
  394.  
  395. begin
  396.    startup;
  397.    repeat
  398.       startgame;
  399.       repeat
  400.          doaturn;
  401.       until landed or anyhit;
  402.    until ask('Again? ','Y or N',['Y','N']) = 'N';
  403.    writeln('Bye!');
  404. end.
  405.  
  406.  
  407.  
  408.  
  409.